﻿// ==========================================================================
// SamplesViewModel.cs
// Silverlight Shapes Library
// ==========================================================================
// Copyright (c) Silverlight Shapes Development Group
// All rights reserved.
// ==========================================================================

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Navigation;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using SD.Components.Navigation.Library;
using SD.Samples.Configuration;

namespace SD.Samples.Views
{    
    /// <summary>
    /// Defines the view model for the Samples page.
    /// </summary>
    [Export]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class SamplesViewModel : ViewModelBase, IPartImportsSatisfiedNotification
    {
        #region Properties

        /// <summary>
        /// Gets or sets the views that are specified in the deployed archives of the application.
        /// </summary>
        /// <value>The views that are specified in the deployed archives of the application.</value>
        [ImportMany(AllowRecomposition = true, RequiredCreationPolicy = CreationPolicy.NonShared)]
        public IEnumerable<Lazy<FrameworkElement, IViewMetadata>> Views { get; set; }

        private ObservableCollection<SourceFileContent> _sourceFiles = new ObservableCollection<SourceFileContent>();
        /// <summary>
        /// Gets the source files of the current sample.
        /// </summary>
        /// <value>The source files of the current sample.</value>
        public ObservableCollection<SourceFileContent> SourceFiles
        {
            get { return _sourceFiles; }
        }

        private string _sampleName;
        /// <summary>
        /// Gets or sets the name of the current sample.
        /// </summary>
        /// <value>The name of the current sample.</value>
        public string SampleName
        {
            get { return _sampleName; }
            set
            {
                if (_sampleName != value)
                {
                    _sampleName = value;
                    RaisePropertyChanged("SampleName");
                }
            }
        }

        private string _samplePage;
        /// <summary>
        /// Gets or sets the path of the current sample.
        /// </summary>
        /// <value>The path of the current sample.</value>
        public string SamplePage
        {
            get { return _samplePage; }
            set
            {
                if (_samplePage != value)
                {
                    _samplePage = value;
                    RaisePropertyChanged("SamplePage");
                }
            }
        }

        private string _sampleDescription;
        /// <summary>
        /// Gets or sets the description of the current sample.
        /// </summary>
        /// <value>The description of the current sample.</value>
        public string SampleDescription
        {
            get { return _sampleDescription; }
            set
            {
                if (_sampleDescription != value)
                {
                    _sampleDescription = value;
                    RaisePropertyChanged("SampleDescription");
                }
            }
        }
        private object _sample;
        /// <summary>
        /// Gets or sets the control that renders the current sample.
        /// </summary>
        /// <value>The control that renders the current sample.</value>
        public object Sample
        {
            get { return _sample; }
            set
            {
                if (_sample != value)
                {
                    _sample = value;
                    RaisePropertyChanged("Sample");
                }
            }
        }
        #endregion

        #region Commands

        private RelayCommand<NavigationContext> _loadCommand;
        /// <summary>
        /// Gets the command to load the view model and the current sample.
        /// </summary>
        /// <value>The command to load the view model and the current sample.</value>
        public RelayCommand<NavigationContext> LoadCommand
        {
            get
            {
                if (_loadCommand == null)
                {
                    _loadCommand = new RelayCommand<NavigationContext>(
                        x =>
                        {
                            LoadSample(x);
                        });
                }

                return _loadCommand;
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Loads the current sample that is specified by the navigation context.
        /// </summary>
        /// <param name="navigationContext">The navigation context of the application.</param>
        private void LoadSample(NavigationContext navigationContext)
        {
            SourceFiles.Clear();

            Sample = null;

            if (navigationContext.QueryString.ContainsKey("Sample"))
            {
                string sampleName = navigationContext.QueryString["Sample"];

                Sample sample = ApplicationSamples.Default.SampleCatagories.SelectMany(s => s.Samples).FirstOrDefault(s => s.Name == sampleName);

                if (sample != null)
                {
                    foreach (SourceFile sourceFile in sample.SourceFiles)
                    {
                        string sourceFileName = sourceFile.FileName.Replace("\\", "_");

                        string path = string.Format(CultureInfo.CurrentCulture, "Source/{0}/{1}.txt", sample.ProjectFile, sourceFileName);

                        WebClient webClient = new WebClient();
                        webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
                        webClient.DownloadStringAsync(new Uri(path, UriKind.Relative), new SourceFileContent(sample.Name, sourceFile.FileName));
                    }

                    if (!string.IsNullOrEmpty(sample.Name))
                    {
                        SampleName = sample.Name.ToUpper(CultureInfo.CurrentCulture);
                    }

                    if (!string.IsNullOrEmpty(sample.Description))
                    {
                        SampleDescription = sample.Description.ToUpper(CultureInfo.CurrentCulture);
                    }

                    SamplePage = sample.Page;
                }

                Lazy<FrameworkElement, IViewMetadata> sampleView = Views.FirstOrDefault(x => x.Metadata.ViewName == sample.Name);

                if (sampleView != null)
                {
                    Sample = sampleView.Value;
                }
            }
        }

        /// <summary>
        /// Handles the DownloadStringCompleted event of the Web Client.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Net.DownloadStringCompletedEventArgs"/> instance containing the event data.</param>
        private void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            WebClient webClient = sender as WebClient;

            webClient.DownloadStringCompleted -= new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);

            if (e.Error == null)
            {
                SourceFileContent sourceFile = e.UserState as SourceFileContent;

                if (sourceFile != null && string.Equals(sourceFile.Sample, SampleName, StringComparison.OrdinalIgnoreCase))
                {
                    sourceFile.Content = e.Result;

                    SourceFiles.Add(sourceFile);
                }
            }
            else
            {
                MessageBox.Show(e.Error.ToString());
            }
        }

        /// <summary>
        /// Called when a part's imports have been satisfied and it is safe to use.
        /// </summary>
        public void OnImportsSatisfied()
        {
            if (Sample == null)
            {
                Lazy<FrameworkElement, IViewMetadata> sampleView = Views.FirstOrDefault(x => string.Equals(x.Metadata.ViewName, SampleName, StringComparison.OrdinalIgnoreCase));

                if (sampleView != null)
                {
                    Sample = sampleView.Value;
                }
            }
        }

        #endregion
    }
}
